﻿using Org.BouncyCastle.Utilities.Encoders;

namespace BJYJ_Admin.Core.Utils.SMUtils
{
    public class SM4Encrypt
    {
        public static readonly string SM4_key = "BJyongjie@1234HL";
        public static readonly string SM4_iv = "595298c7c6fd271f0402f804c33d3f66";
        /// <summary>
        /// 加密ecb模式
        /// </summary>
        /// <param name="plainText">明文</param>
        /// <param name="secretKey">密钥</param>
        /// <param name="hexString">明文是否是十六进制</param>
        /// <returns>返回密文</returns>
        public static string Encrypt_ECB(String plainText, String secretKey = "", bool hexString = false)
        {
            if (string.IsNullOrWhiteSpace(secretKey))
                secretKey = SM4_key;
            Sm4Context ctx = new Sm4Context();
            ctx.isPadding = true;
            ctx.mode = Sm4.SM4_ENCRYPT;
            byte[] keyBytes;
            if (hexString)
            {
                keyBytes = Hex.Decode(secretKey);
            }
            else
            {
                keyBytes = Encoding.Default.GetBytes(secretKey);
            }
            Sm4 sm4 = new Sm4();
            sm4.sm4_setkey_enc(ctx, keyBytes);
            byte[] encrypted = sm4.sm4_crypt_ecb(ctx, Encoding.Default.GetBytes(plainText));
            String cipherText = Convert.ToBase64String(encrypted);
            return cipherText;
        }

        /// <summary>
        /// 解密ECB模式
        /// </summary>
        /// <param name="cipherText">密文</param>
        /// <param name="secretKey">密钥</param>
        /// <param name="hexString">明文是否是十六进制</param>
        /// <returns>返回明文</returns>
        public static String Decrypt_ECB(String cipherText, String secretKey = "", bool hexString = false)
        {

            if (string.IsNullOrWhiteSpace(secretKey))
                secretKey = SM4_key;
            Sm4Context ctx = new Sm4Context();
            ctx.isPadding = true;
            ctx.mode = Sm4.SM4_DECRYPT;

            byte[] keyBytes;
            if (hexString)
            {
                keyBytes = Hex.Decode(secretKey);
            }
            else
            {
                keyBytes = Encoding.Default.GetBytes(secretKey);
            }

            Sm4 sm4 = new Sm4();
            sm4.sm4_setkey_dec(ctx, keyBytes);
            byte[] decrypted = sm4.sm4_crypt_ecb(ctx, Convert.FromBase64String(cipherText));
            return Encoding.Default.GetString(decrypted);
        }


        /// <summary>
        /// 加密CBC模式
        /// </summary>
        /// <param name="secretKey">密钥</param>
        /// <param name="hexString">明文是否是十六进制</param>
        /// <param name="iv">偏移量</param>
        /// <param name="plainText">明文</param>
        /// <returns>返回密文</returns>
        public static String Encrypt_CBC(String plainText, String secretKey = "", bool hexString = false, string iv = "")
        {
            if (string.IsNullOrWhiteSpace(secretKey))
                secretKey = SM4_key;
            if (string.IsNullOrWhiteSpace(iv))
                iv = SM4_iv;
            Sm4Context ctx = new Sm4Context();
            ctx.isPadding = true;
            ctx.mode = Sm4.SM4_ENCRYPT;
            byte[] keyBytes;
            byte[] ivBytes;
            if (hexString)
            {
                keyBytes = Hex.Decode(secretKey);
                ivBytes = Hex.Decode(iv);
            }
            else
            {
                keyBytes = Convert.FromBase64String(secretKey);
                ivBytes = Convert.FromBase64String(iv);
            }
            Sm4 sm4 = new Sm4();
            sm4.sm4_setkey_enc(ctx, keyBytes);
            byte[] encrypted = sm4.sm4_crypt_cbc(ctx, ivBytes, Encoding.UTF8.GetBytes(plainText));
            String cipherText = Convert.ToBase64String(encrypted);
            if (cipherText != null && cipherText.Length > 0)
            {
                cipherText = Regex.Replace(cipherText, @"/(\s*|\t|\r|\n)/g", "");
            }
            return cipherText;
        }



        /// <summary>
                /// 解密CBC模式
                /// </summary>
                /// <param name="secretKey">密钥</param>
                /// <param name="hexString">明文是否是十六进制</param>
                /// <param name="iv"></param>
                /// <param name="cipherText">密文</param>
                /// <returns>返回明文</returns>
        public static String Decrypt_CBC(String cipherText, String secretKey = "", bool hexString = false, string iv = "")
        {
            if (string.IsNullOrWhiteSpace(secretKey))
                secretKey = SM4_key;
            if (string.IsNullOrWhiteSpace(iv))
                iv = SM4_iv;
            Sm4Context ctx = new Sm4Context();
            ctx.isPadding = true;
            ctx.mode = Sm4.SM4_DECRYPT;
            byte[] keyBytes;
            byte[] ivBytes;
            if (hexString)
            {
                keyBytes = Hex.Decode(secretKey);
                ivBytes = Hex.Decode(iv);
            }
            else
            {
                keyBytes = Encoding.Default.GetBytes(secretKey);
                ivBytes = Encoding.Default.GetBytes(iv);
            }
            Sm4 sm4 = new Sm4();
            sm4.sm4_setkey_dec(ctx, keyBytes);
            byte[] decrypted = sm4.sm4_crypt_cbc(ctx, ivBytes, Convert.FromBase64String(cipherText));
            return Encoding.Default.GetString(decrypted);
        }
    }
}
